unit uCommon;

interface

uses
  Windows, SysUtils, IniFiles, Classes;

const
  INI_FILE_NAME = 'SuperTREx.ini';
  INI_SETTINGS = 'SETTINGS';
  INI_WorkDir = 'WorkDir';
  INI_TempDir = 'TempDir';
  INI_BasePort = 'BasePort';
  INI_AltPort = 'AltPort';
  INI_Slave = 'Slave';
  INI_MainTop = 'MainTop';
  INI_MainLeft = 'MainLeft';
  INI_ActionTop = 'ActionTop';
  INI_ActionLeft = 'ActionLeft';
  INI_ActionWidth = 'ActionWidth';
  INI_ActionHeight = 'ActionHeight';

var
  MyIniFile: TIniFile;
  BasePort, AltPort: Word;
  strBasePort, strAltPort: string;
  fMoreInfo, fPathLock, fMkDirDrvTbl: Boolean;
  IniFile, FirmwarePath, TempDir, VerInfo, WorkDir: string;
  Slave, MainTop, MainLeft, ActionTop, ActionLeft, ActionWidth, ActionHeight, AutoTestTop, AutoTestLeft, AutoTestWidth, AutoTestHeight, FirmwareTop, FirmwareLeft, FirmwareWidth, FirmwareHeight: Integer;

function GetAppPath(): string;

function OEMChar(aByte: Byte): Char;

function CharOEM(aByte: Byte): Char;

function IsFileInUse(AName: string): Boolean;

function GetBuildInfo: string; overload;

procedure GetBuildInfo(FileName: string; var vs: string); overload;

procedure InitIniFile;

procedure SaveIniFile;

implementation

function GetAppPath(): string;
begin
  Result := ExtractFilePath(ParamStr(0));
end;

function OEMChar(aByte: Byte): Char;
var
  psr: string;
begin
  psr := Char(aByte) + #0;
  OemToCharA(@psr[1], @psr[1]);
  Result := psr[1];
end;

function CharOEM(aByte: Byte): Char;
var
  psr: string;
begin
  psr := Char(aByte) + #00;
  CharToOemA(@psr[1], @psr[1]);
  Result := psr[1];
end;

function IsFileInUse(AName: string): Boolean;
var
  hFileRes: HFILE;
begin
  Result := False;
  if not FileExists(AName) then
    Exit;
  hFileRes := CreateFile(PChar(AName), GENERIC_READ or GENERIC_WRITE, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  Result := hFileRes = INVALID_HANDLE_VALUE;
  if not Result then
    CloseHandle(hFileRes);
end;

function GetBuildInfo(): string; overload;
var
  VerInfoSize, VerValueSize, Dummy: DWORD;
  VerInfo: Pointer;
  VerValue: PVSFixedFileInfo;
  V1, V2, V3, V4: Word;
begin
  VerInfoSize := GetFileVersionInfoSize(PChar(ParamStr(0)), Dummy);
  if VerInfoSize = 0 then
    Exit;
  GetMem(VerInfo, VerInfoSize);
  if not GetFileVersionInfo(PChar(ParamStr(0)), 0, VerInfoSize, VerInfo) then
    Exit;
  VerQueryValue(VerInfo, '\', Pointer(VerValue), VerValueSize);
  with VerValue^ do
  begin
    V1 := dwFileVersionMS shr 16;
    V2 := dwFileVersionMS and $FFFF;
    V3 := dwFileVersionLS shr 16;
    V4 := dwFileVersionLS and $FFFF;
  end;
  Result := IntToStr(V1) + '.' + IntToStr(V2) + '.' + IntToStr(V3) + '.' + IntToStr(V4);
  FreeMem(VerInfo, VerInfoSize);
end;

procedure GetBuildInfo(FileName: string; var vs: string); overload;
var
  VerInfoSize, VerValueSize, Dummy: DWORD;
  VerInfo: Pointer;
  VerValue: PVSFixedFileInfo;
  V1, V2, V3, V4: Word;
begin
  vs := '';
  if not FileExists(FileName) then
    Exit;
  VerInfoSize := GetFileVersionInfoSize(PChar(FileName), Dummy);
  if VerInfoSize = 0 then
    Exit;
  GetMem(VerInfo, VerInfoSize);
  if not GetFileVersionInfo(PChar(FileName), 0, VerInfoSize, VerInfo) then
    Exit;
  VerQueryValue(VerInfo, '\', Pointer(VerValue), VerValueSize);
  with VerValue^ do
  begin
    V1 := dwFileVersionMS shr 16;
    V2 := dwFileVersionMS and $FFFF;
    V3 := dwFileVersionLS shr 16;
    V4 := dwFileVersionLS and $FFFF;
    vs := IntToStr(V1) + '.' + IntToStr(V2) + '.' + IntToStr(V3) + '.' + IntToStr(V4);
  end;
  FreeMem(VerInfo, VerInfoSize);
end;

procedure ResToFile(const ResName, ResType, FileName: string);
var
  Res: TResourceStream;
begin
  Res := TResourceStream.Create(HInstance, ResName, PChar(ResType));
  try
    Res.SaveToFile(FileName);
  finally
    Res.Free;
  end;
end;

function CheckIniFile(path: string): Boolean;
begin
  if not FileExists(path) then
  begin
    ResToFile('INI_File', 'INI', path);
  end;
  Result := FileExists(path);
end;

procedure CheckWorkDir;
begin
  if WorkDir = '' then
  begin
    WorkDir := GetAppPath + 'Firmware\';
    TempDir := GetAppPath + 'Temp\';
  end;
  if not DirectoryExists(WorkDir) then
  begin
    if not ForceDirectories(WorkDir) then
    begin
      WorkDir := GetAppPath + 'Firmware\';
      TempDir := GetAppPath + 'Temp\';
    end;
    if not DirectoryExists(WorkDir) then
      ForceDirectories(WorkDir);
    if not DirectoryExists(TempDir) then
      ForceDirectories(TempDir);
  end;
  if not DirectoryExists(TempDir) then
  begin
    if not ForceDirectories(TempDir) then
    begin
      TempDir := GetAppPath + 'Temp\';
      if not DirectoryExists(TempDir) then
        ForceDirectories(TempDir);
    end;
  end;
end;

procedure InitIniFile;
begin
  VerInfo := GetBuildInfo;
  IniFile := GetAppPath + INI_FILE_NAME;
  CheckIniFile(IniFile);
  MyIniFile := TIniFile.Create(IniFile);
  WorkDir := MyIniFile.ReadString(INI_SETTINGS, INI_WorkDir, '');
  TempDir := MyIniFile.ReadString(INI_SETTINGS, INI_TempDir, '');
  strBasePort := MyIniFile.ReadString(INI_SETTINGS, INI_BasePort, '');
  strAltPort := MyIniFile.ReadString(INI_SETTINGS, INI_AltPort, '');
  BasePort := StrToInt(strBasePort.Replace('0x', '$'));
  AltPort := StrToInt(strAltPort.Replace('0x', '$'));
  Slave := MyIniFile.ReadInteger(INI_SETTINGS, INI_Slave, 1);
  MainTop := MyIniFile.ReadInteger(INI_SETTINGS, INI_MainTop, 0);
  MainLeft := MyIniFile.ReadInteger(INI_SETTINGS, INI_MainLeft, 0);
  ActionTop := MyIniFile.ReadInteger(INI_SETTINGS, INI_ActionTop, 0);
  ActionLeft := MyIniFile.ReadInteger(INI_SETTINGS, INI_ActionLeft, 0);
  ActionWidth := MyIniFile.ReadInteger(INI_SETTINGS, INI_ActionWidth, 0);
  ActionHeight := MyIniFile.ReadInteger(INI_SETTINGS, INI_ActionHeight, 0);
end;

procedure SaveIniFile;
begin
  strBasePort := '0x' + IntToHex(BasePort, 4);
  strAltPort := '0x' + IntToHex(AltPort, 4);
  MyIniFile.WriteString(INI_SETTINGS, INI_BasePort, strBasePort);
  MyIniFile.WriteString(INI_SETTINGS, INI_AltPort, strAltPort);
  MyIniFile.WriteInteger(INI_SETTINGS, INI_Slave, Slave);
  MyIniFile.WriteInteger(INI_SETTINGS, INI_MainTop, MainTop);
  MyIniFile.WriteInteger(INI_SETTINGS, INI_MainLeft, MainLeft);
  MyIniFile.WriteInteger(INI_SETTINGS, INI_ActionTop, ActionTop);
  MyIniFile.WriteInteger(INI_SETTINGS, INI_ActionLeft, ActionLeft);
  MyIniFile.WriteInteger(INI_SETTINGS, INI_ActionWidth, ActionWidth);
  MyIniFile.WriteInteger(INI_SETTINGS, INI_ActionHeight, ActionHeight);
end;

end.

